<template>
  <div class="flex flex-col h-full w-full">
    <!-- api 接口选择区域 -->
    <div class="flex gap-2 ml-4 flex-wrap">
      <n-button v-for="api in savedApis" :key="api.ID" :type="currentApi.ID === api.ID ? 'primary' : 'default'"
        @click="selectRequest(api)">
        {{ api.name }}
      </n-button>
      <n-button circle :type="currentApi.ID === 0 ? 'primary' : 'default'" @click="addNewRequest">+</n-button>
    </div>
    <!-- 请求区域 -->
    <div class="p-4 border-b">
      <div class="flex gap-2 mb-4">
        <!-- 请求方法选择 -->
        <n-select v-model:value="currentApi.method" :options="methodOptions" class="w-24" />
        <!-- URL 输入框 -->
        <n-input v-model:value="currentApi.url" placeholder="请输入请求 URL" class="flex-1" />
        <!-- 发送按钮 -->
        <n-button type="primary" @click="sendRequest" :loading="loading">
          测试请求
        </n-button>
        <n-button type="info" @click="saveRequest">
          保存请求
        </n-button>
      </div>

      <!-- 请求配置区域 -->
      <div class="flex gap-4">
        <!-- 请求头 -->
        <div class="flex-1">
          <div class="font-medium mb-2">请求头</div>
          <div class="headers-list">
            <div v-for="(header, index) in headers" :key="index" class="flex gap-2 mb-2">
              <n-input v-model:value="header.key" placeholder="Key" />
              <n-input v-model:value="header.value" placeholder="Value" />
              <n-button @click="removeHeader(index)" quaternary>
                <n-icon>
                  <Close />
                </n-icon>
              </n-button>
            </div>
            <n-button @click="addHeader" dashed class="mt-2">
              添加请求头
            </n-button>
          </div>
        </div>

        <!-- 请求体 -->
        <div class="flex-1 border-l pl-4">
          <div class="font-medium mb-2">请求体</div>
          <div class="flex items-center gap-2 mb-2">
            <n-button quaternary size="small" @click="formatRequestBody">
              格式化
            </n-button>
          </div>
          <Codemirror v-model="currentApi.body" :style="{ height: '200px' }" :autofocus="false" :indent-with-tab="true"
            :tabSize="2" :extensions="extensions" />
        </div>
      </div>
    </div>

    <!-- 响应区域 -->
    <div class="flex-1 p-4 overflow-auto">
      <template v-if="response">
        <div class="mb-4">
          <span class="font-bold">状态码：</span>
          <n-tag :type="response.status === 200 ? 'success' : 'error'">
            {{ response.status }}
          </n-tag>
        </div>

        <n-tabs type="line" animated>
          <!-- 响应体 -->
          <n-tab-pane name="response" tab="响应体">
            <div class="flex items-center gap-2 mb-2">
              <n-button quaternary size="small" @click="responseEditable = !responseEditable">
                {{ responseEditable ? '退出编辑' : '编辑响应' }}
              </n-button>
              <n-button quaternary size="small" @click="formatResponseData">
                格式化
              </n-button>
            </div>
            <Codemirror v-model="responseText" :style="{ height: '500px' }" :autofocus="false" :indent-with-tab="true"
              :tabSize="2" :extensions="extensions" :readonly="!responseEditable" line-wrapping />
          </n-tab-pane>

          <!-- 响应头 -->
          <n-tab-pane name="response.headers" tab="响应头">

            <n-table bordered :single-line="false" striped>
              <thead>
                <tr>
                  <th width="250">Key</th>
                  <th>Value</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(value, key) in response.headers" :key="key">
                  <td>{{ key }}</td>
                  <td>{{ value }}</td>
                </tr>
              </tbody>
            </n-table>
          </n-tab-pane>
        </n-tabs>
      </template>

      <!-- 错误信息 -->
      <n-alert v-if="error" type="error" :title="error.message" class="mt-4" />
    </div>

    <!-- 保存 API 模态框 -->
    <n-modal v-model:show="showSaveModal" preset="dialog" title="保存 API">
      <n-form>
        <n-form-item label="API 名称">
          <n-input v-model:value="apiName" placeholder="请输入 API 名称" />
        </n-form-item>
      </n-form>
      <template #action>
        <n-button type="primary" @click="confirmSave">确定</n-button>
      </template>
    </n-modal>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Close, AddSharp } from '@vicons/ionicons5'
import {
  NSelect,
  NInput,
  NButton,
  NTabs,
  NTabPane,
  NIcon,
  NTag,
  NTable,
  NAlert,
  NModal,
  NForm,
  NFormItem,
  useMessage
} from 'naive-ui'
import { SendRequest, AddApi, GetApis, SaveApi } from '../../wailsjs/go/apis/Apis'
import { Codemirror } from 'vue-codemirror'
import { json } from '@codemirror/lang-json'
import { xml } from '@codemirror/lang-xml'
import { oneDark } from '@codemirror/theme-one-dark'

const props = defineProps<{
  groupId?: number
}>()

const methodOptions = [
  { label: 'GET', value: 'GET' },
  { label: 'POST', value: 'POST' },
  { label: 'PUT', value: 'PUT' },
  { label: 'DELETE', value: 'DELETE' },
  { label: 'PATCH', value: 'PATCH' },
]

const currentApi = ref({})
const method = ref('GET')
const url = ref('')
const headers = ref<{ key: string; value: string }[]>([])
const body = ref('{\n  \n}')
const response = ref<any>(null)
const error = ref<Error | null>(null)
const loading = ref(false)

const extensions = [
  json(),
  xml(),
  // oneDark
]

const responseText = ref('')
const responseEditable = ref(false)

const showSaveModal = ref(false)
const apiName = ref('')
const savedApis = ref([])
const message = useMessage()

const addHeader = () => {
  headers.value.push({ key: '', value: '' })
}

const removeHeader = (index: number) => {
  headers.value.splice(index, 1)
}

const formatResponse = (data: any) => {
  try {
    return JSON.stringify(JSON.parse(data), null, 2)
  } catch {
    if (typeof data === 'string' && data.trim().startsWith('<?xml')) {
      return formatXML(data)
    }
    return String(data)
  }
}

const formatResponseData = () => {
  try {
    const parsed = JSON.parse(responseText.value)
    responseText.value = JSON.stringify(parsed, null, 2)
  } catch {
    if (responseText.value.trim().startsWith('<')) {
      responseText.value = formatXML(responseText.value)
    } else {
      console.warn('无法格式化非 JSON/XML 数据')
    }
  }
}

const formatRequestBody = () => {
  try {
    const parsed = JSON.parse(body.value)
    body.value = JSON.stringify(parsed, null, 2)
  } catch (err) {
    console.warn('无法格式化非 JSON 数据')
  }
}

const formatXML = (xml: string) => {
  let formatted = ''
  let indent = ''
  const tab = '  '

  xml.split(/>\s*</).forEach(node => {
    if (node.match(/^\/\w/)) {
      indent = indent.substring(tab.length)
    }

    formatted += indent + '<' + node + '>\r\n'

    if (node.match(/^<?\w[^>]*[^\/]$/)) {
      indent += tab
    }
  })

  return formatted
    .replace(/\s*<\?xml/g, '<?xml')
    .replace(/\s*\/>/g, '/>')
}

const saveRequest = async () => {
  if (currentApi.value.ID === 0) {
    showSaveModal.value = true
  } else {
    currentApi.value.headers = JSON.stringify(headers.value)
    await SaveApi(currentApi.value)
    message.success('保存成功')
  }
}

const confirmSave = async () => {
  if (!apiName.value) {
    message.error('请输入 API 名称')
    return
  }
  let headersObj = headers.value.reduce((acc, curr) => {
    if (curr.key) {
      acc[curr.key] = curr.value
    }
    return acc
  }, {})
  try {
    let err = await AddApi({
      groupId: Number(props.groupId),
      name: apiName.value,
      method: method.value,
      url: url.value,
      headers: JSON.stringify(headersObj),
      params: '',
      body: body.value,
      description: ''
    })
    if (err) {
      message.error('保存失败: ' + err)
    } else {
      message.success('保存成功')
      showSaveModal.value = false
      apiName.value = ''
      await loadSavedApis()
    }
  } catch (err) {
    message.error('保存失败: ' + (err as Error).message)
  }
}

const loadSavedApis = async () => {
  if (props.groupId) {
    savedApis.value = await GetApis(props.groupId)
    if (savedApis.value.length > 0) {
      currentApi.value = savedApis.value[0]
    } else {
      currentApi.value = { ID: 0 }
    }
  }
}

onMounted(() => {
  loadSavedApis()
})

const sendRequest = async () => {
  loading.value = true
  error.value = null

  try {
    const res = await SendRequest({
      Method: method.value,
      Url: url.value,
      Body: {
        Type: 'raw',
        Raw: body.value
      }
    })
    response.value = {
      status: res.StatusCode,
      headers: res.Headers,
      data: res.Data
    }
    responseText.value = formatResponse(res.Data)
  } catch (err) {
    error.value = err as Error
  } finally {
    loading.value = false
  }
}
const addNewRequest = () => {
  currentApi.value = { ID: 0, method: 'GET', url: '', headers: {}, body: '{\n  \n}' }
}

const selectRequest = (api: any) => {
  currentApi.value = api
  headers.value = Object.entries(JSON.parse(api.headers) || {}).map(([key, value]) => ({
    key,
    value: value as string
  }))
}
</script>